<template>
  <div class="course-catalog">
    <template v-for="(item, index) in courseItems">
      <div v-if="item.children && item.children.length > 0" :key="index" class="catalog-list">
        <div class="catalog-list-title" :class="getTheme()" @click="toggleExpand(item.seq)">
          <div class="title" :title="item.title">{{ item.title }}</div>
          <div class="operation">
            <div v-if="isExpanded(item.seq)">
              <span>收起</span>
              <span><CaretUpOutlined /></span>
            </div>
            <div v-else>
              <span>展开</span>
              <span><CaretDownOutlined /></span>
            </div>
          </div>
        </div>
        <div v-if="isExpanded(item.seq)" class="catalog-list-data">
          <div v-for="(subItem, subIndex) in item.children" :key="subIndex" @click="toggleSelect(subItem.seq)" class="catalog-item"
            :class="[ getTheme(), isSelected(subItem.seq)? 'selected' : '']">
            <slot name="title" :item="subItem" :index="subIndex">
              <div class="title" :title="subItem.title">{{ subItem.title }}</div>
            </slot>
            <slot name="operation" :item="subItem" :index="subIndex">
              <div v-if="showProgress" class="operation" :class="subItem.progressClass">{{ subItem.progressInfo}}</div>
            </slot>
          </div>
        </div>
      </div>
      <div v-else :key="1000+index" @click="toggleSelect(item.seq)" class="catalog-item"
        :class="[ getTheme(), isSelected(item.seq)? 'selected' : '']">
        <slot name="title" :item="item" :index="index">
          <div class="title" :title="item.title">{{ item.title }}</div>
        </slot>
        <slot name="operation" :item="item" :index="index">
          <div v-if="showProgress" class="operation" :class="item.progressClass">{{ item.progressInfo}}</div>
        </slot>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from "vue";
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons-vue';
import { CourseCatalogItem } from '@/models/course';

// 组件属性
const props = defineProps({
  items: {
    type: Array,
    required: true,
    default: () => []
  },
  resetTitle: {
    type: Boolean,
    required: false,
    default: () => false
  },
  progresses: {
    type: Object,
    required: false,
    default: () => []
  },
  showProgress: {
    type: Boolean,
    required: false,
    default: () => false
  },
  selectedKeys: {
    type: Array as () => number[],
    required: false,
    default: () => []
  },
  theme: {
    type: String,
    required: false,
    default: ''
  },
})

// 响应式数据
const openKeys = ref([] as number[])
const selectedKeys = ref([] as number[])
const courseItems = ref([] as CourseCatalogItem[])
const showProgress = ref(false)

// 事件处理
const emit = defineEmits(['click'])

// 获取组件主题（缺省：light；可选：light、dark、light-small、dark-small）
const getTheme = () => {
  return props.theme ? (props.theme.startsWith('theme-') ? props.theme : 'theme-' + props.theme) : 'theme-light';
}

const getSeqProgress = (seq: number): number => {
  const progress=(props.progresses && (props.progresses[seq] || props.progresses[""+seq])) || 0;
  return parseInt(""+progress);
}

const getSeqProgressInfo = (seq: number, videoLength: number): string => {
  let second: number= getSeqProgress(seq);
  if (second > 0) {
    if (second >= videoLength) {
      return "已学完";
    } else {
      return "已学习" + Math.ceil(second*100/videoLength) + "%";
    }
  } else {
    return "未观看";
  }
}

const getSeqProgressClass = (seq: number, videoLength: number): string  => {
  let second: number= getSeqProgress(seq);
  return (second > 0 && second < videoLength) ? "underway" : "";
}

const getTitle = (videoTitle: string): string => {
  let title = videoTitle.split('、');
  return title.length > 1 ? title[1] : title[0];
}

const isExpanded = (key: number) => {
  return openKeys.value.includes(key);
};

const isSelected = (key: number) => {
  return selectedKeys.value.includes(key);
};

const toggleExpand = (key: number) => {
  if (isExpanded(key)) {
    openKeys.value = openKeys.value.filter(k => k !== key);
  } else {
    openKeys.value.push(key);
  }
};

const toggleSelect = (key: number) => {
  if (isSelected(key)) {
    selectedKeys.value = selectedKeys.value.filter(k => k !== key);
  } else {
    if (selectedKeys.value.length > 0) {
      selectedKeys.value = [];
    }
    selectedKeys.value.push(key);
  }
};

const initData = () => {
  courseItems.value = [];
  const videoList = props.items || [];
  selectedKeys.value = props.selectedKeys || [];
  showProgress.value = props.showProgress || false;
  let chapterIndex = 0;
  let lessonIndex = 0;
  let lastItem: CourseCatalogItem | null= null;
  videoList.forEach((video, index) => {
    let item = {
      seq: index,
      key: video.pkId
    } as CourseCatalogItem;
    video.videoLength = video.aliLength || video.videoLength || video.videoSize || 0;
    if (video.isDir && video.isDir == 1) {
      chapterIndex ++;
      if (props.resetTitle) {
        item.title = '第' + chapterIndex + '章　' + getTitle(video.videoTitle);
      } else {
        item.title = video.videoTitle;
      }
      openKeys.value.push(item.seq);
    } else {
      lessonIndex ++;
      if (props.resetTitle) {
        item.title = '第' + lessonIndex + '讲　' + getTitle(video.videoTitle);
      } else {
        item.title = video.videoTitle;
      }
      item.source = video.source;
      item.vid = video.vid;
      item.playauth = video.playauth;
      if (showProgress.value) {
        item.progressInfo = getSeqProgressInfo(index, video.videoLength);
        item.progressClass = getSeqProgressClass(index, video.videoLength);
      }
    }
    if (!video.sourceId) {
      if (video.isDir && video.isDir == 1) {
        item.children = [] as CourseCatalogItem[];
        lastItem = item;
      }
      courseItems.value.push(item);
    } else {
      if (lastItem) {
        lastItem.children.push(item);
      } else {
        courseItems.value.push(item);
      }
    }
  });
}

onMounted(() => {
  initData();
});

// 监听 tags 的变化
watch(() => props.items, () => {
  initData();
}, { immediate: true });

// 监听 tags 的变化
watch(() => props.selectedKeys, () => {
  // console.log('CourseCatalog props.selectedKeys: ', props.selectedKeys)
  selectedKeys.value = props.selectedKeys || [];
}, { immediate: true });
</script>

<style lang="less" scoped>
.course-catalog {
  width: 100%;
  height: 100%;

  &.theme-light, &.theme-light-small {
    background: @white;
  }

  &.theme-dark, &.theme-dark-small {
    background: rgba(0,0,0,0.8);
  }

  .catalog-list {
    display: flex;
    flex-direction: column;
    
    .catalog-list-title {
      display: flex;
      flex-direction: row;
      justify-items: space-between;
      border-radius: 12px;
      cursor: pointer;

      &.theme-light, &.theme-light-small {
        background: @grey-bg;

        .title {
          color: @font-black;
        }

        .operation {
          color: @font-grey;
        }
      }

      &.theme-dark, &.theme-dark-small {
        color: @white;
        background-color: rgba(255, 255, 255, 0.4);

        .title {
          color: @white;
        }

        .operation {
          color: @white;
        }
      }

      &.theme-dark, &.theme-light {
        padding: 20px;
      }

      &.theme-dark-small, &.theme-light-small {
        padding: 18px 20px;
      }

      .title {
        flex: 1;
        height: 20px;
        line-height: 20px;
        font-size: 20px;
        font-weight: 500;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .operation {
        height: 20px;
        line-height: 20px;
        text-align: right;
        font-size: 16px;
        font-weight: 400;
        color: @font-grey;
        margin-left: 20px;
      }
    }

    .catalog-list-title:hover {
      background: @red-bg;
    }
    
    .catalog-list-data {
      display: flex;
      flex-direction: column;
      margin-top: 10px;

      .catalog-item:not(:first-child) {
        margin-top: 10px;
      }
    }
  }
  
  .catalog-list:not(:first-child) {
    margin-top: 10px;
  }

  :deep(.catalog-item) {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-items: space-between;
    border-radius: 12px;
    padding: 18px;

    &.theme-light, &.theme-light-small {
      color: @font-black;
      background: @white-bg;
      border: 2px solid @white-bg;

      .title {
        color: @font-black;
      }

      .operation {
        color: @font-grey;
      }
    }

    &.theme-dark, &.theme-dark-small {
      background: transparent;
      border: 2px solid @font-grey-disable;
      opacity: 0.3;

      .title {
        color: @white;
      }

      .operation {
        color: @white;
      }
    }

    &.theme-dark-small, &.theme-light-small {
      padding: 16px 18px;

      .title {
        font-size: 16px;

        a {
          font-size: 16px;
        }
      }

      .operation {
        font-size: 14px;
      }
    }

    .title {
      flex: 1;
      height: 20px;
      line-height: 20px;
      font-size: 18px;
      font-weight: 500;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;

      a {
        font-size: 18px;
      }
    }
    .operation {
      height: 20px;
      line-height: 20px;
      text-align: right;
      font-size: 16px;
      font-weight: 400;
      margin-left: 20px;

      &.underway {
        color: @green;
      }
    }
    &.selected {
      border-color: @font-red;
      background: @red-bg;

      .title {
        color: @font-red;
      }
    }
    
    &:hover {
      background: @red-bg;
    }

    &:not(:first-child) {
      margin-top: 10px;
    }
  }
}
</style>
